#include "main.h"
#include "cJSON.h"
#include "mqtt.h"
#include "sensor.h"
#include <string.h>

extern TIM_HandleTypeDef htim4;
sensor_t g_sensor;




static int led_open()
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
	return 0;
}

static int led_close()
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
	return 0;
}

static int led_read(int *val)
{
	if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) ==  GPIO_PIN_SET){
		*val = 0;
	}else{
		*val = 1;
	}
	return 0;
}


static int sensor_send_led(int val)
{
	char *str;
	cJSON *root = NULL;
	cJSON *reported = NULL;

	root = cJSON_CreateObject();
	reported = cJSON_CreateObject();
	cJSON_AddItemToObject(root, "reported", reported);
	cJSON_AddItemToObject(reported, g_sensor.led.name, cJSON_CreateBool(val));
	str = cJSON_PrintUnformatted(root);
	mqtt_publish_update(str, strlen(str));
	cJSON_Delete(root);
	cJSON_free(str);
	return 0;
}


static int sensor_send_dht11(int tmp, int hum)
{
	char *str;
	cJSON *root = NULL;
	cJSON *reported = NULL;
	root = cJSON_CreateObject();
	reported = cJSON_CreateObject();
	cJSON_AddItemToObject(root, "reported", reported);
	cJSON_AddItemToObject(reported, g_sensor.hum.name, cJSON_CreateNumber(hum));
	cJSON_AddItemToObject(reported, g_sensor.tmp.name, cJSON_CreateNumber(tmp));
	str = cJSON_PrintUnformatted(root);
	mqtt_publish_update(str, strlen(str));
	cJSON_Delete(root);
	cJSON_free(str);
	return 0;
}
// 1-10000
static void delay_us(int us)
{
	us = us + us;
	if(us > 20000){
		while(1);
	}
	__HAL_TIM_SET_COUNTER(&htim4, us-3);
	while(!(__HAL_TIM_GET_COUNTER(&htim4) & 0x8000));
}

static int dht11_pin_write(int val)
{
	if(val){
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
	}else{
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
	}

}

static int dht11_pin_read()
{
	return HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9);
}

static int dht11_init()
{
	dht11_pin_write(0);
	HAL_Delay(20);
	dht11_pin_write(1);
	HAL_Delay(1000);
	__HAL_TIM_ENABLE(&htim4);
	return 0;
}

static int dht11_start()
{
	int i;
	dht11_pin_write(0);
	HAL_Delay(20);
	dht11_pin_write(1);
	for(i=0; i< 5;i++){
		if(dht11_pin_read() == 1){
			delay_us(10);
		}else{
			break;
		}
	}
	if((i < 1) || (i >4 )){
		return -1;
	}
	for(i=0; i< 10;i++){
		if(dht11_pin_read() == 0){
			delay_us(10);
		}else{
			break;
		}
	}
	if((i < 7) || (i > 9)){
		return -1;
	}
	for(i=0; i< 10;i++){
		if(dht11_pin_read() == 1){
			delay_us(10);
		}else{
			break;
		}
	}
	if((i < 7) || (i > 9)){
		return -1;
	}
	return 0;
}

static int dht11_read_bit(uint8_t *bit)
{
	int i;
	for(i=0; i< 6;i++){
		if(dht11_pin_read() == 0){
			delay_us(10);
		}else{
			break;
		}
	}
	if((i < 4) || (i >= 6)){
		return -1;
	}
	for(i=0; i< 10;i++){
		if(dht11_pin_read() == 1){
			delay_us(10);
		}else{
			break;
		}
	}
	if(i < 2){
		return -1;
	}
	if(i >4){
		*bit =1;
	}else{
		*bit =0;
	}
	return 0;
}
static int dht11_read(int *tmp, int *hum)
{
	int i;
	uint8_t bit;
	int hum_h = 0, hum_l = 0;
	int tmp_h = 0, tmp_l = 0;
	dht11_start();
	for(i=0;i<8;i++){
		if(dht11_read_bit(&bit)< 0){
			return -1;
		}
		if(bit){
			hum_h |= 1 << (7-i);
		}
	}
	for(i=0;i<8;i++){
		if(dht11_read_bit(&bit)< 0){
			return -1;
		}
		if(bit){
			hum_l |= 1 << (7-i);
		}
	}
	for(i=0;i<8;i++){
		if(dht11_read_bit(&bit)< 0){
			return -1;
		}
		if(bit){
			tmp_h |= 1 << (7-i);
		}
	}
	for(i=0;i<8;i++){
		if(dht11_read_bit(&bit)< 0){
			return -1;
		}
		if(bit){
			tmp_l |= 1 << (7-i);
		}
	}
	*tmp = tmp_h;
	*hum = hum_h;
	return 0;
}

int sensor_int()
{
	int i;
	int led_val;
	int tmp,hum;
	g_sensor.led.name = "LED";
	g_sensor.hum.name = "humidity";
	g_sensor.tmp.name = "temperature";
	led_close();
	led_read(&led_val);
	g_sensor.led.val = led_val;
	sensor_send_led(led_val);
	dht11_init();
	if (dht11_read(&tmp, &hum) < 0){
		return -1;
	}
	g_sensor.hum.val = hum;
	g_sensor.tmp.val = tmp;
	sensor_send_dht11(tmp, hum);
//	while(1){
//		for(i=0;i< 1000000;i++){
//			delay_us(10);
//		}
//		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
//	}
	return 0;
}



int sensor_data_set(char *str)
{
	cJSON *root = NULL;
	cJSON *desired = NULL;
	cJSON *led = NULL;

	root = cJSON_Parse(str);
	desired = cJSON_GetObjectItem(root, "desired");
	led = cJSON_GetObjectItem(desired, g_sensor.led.name);

	if(led->valueint == 0){
		led_close();
	}else{
		led_open();
	}
	cJSON_Delete(root);
	return 0;
}

int delay_dht11;
int sensor_data_get()
{
	int led_val;
	int tmp, hum;
	led_read(&led_val);
	if(led_val != g_sensor.led.val){
		sensor_send_led(led_val);
		g_sensor.led.val = led_val;
	}
	if(delay_dht11 < 100){
		delay_dht11++;
		return 0;
	}
	delay_dht11 = 0;
	if (dht11_read(&tmp, &hum) < 0){
		return -1;
	}
	g_sensor.hum.val = hum;
	g_sensor.tmp.val = tmp;
	sensor_send_dht11(tmp, hum);
	return 0;
}
